编译ffmpeg安卓库(clang篇),含armeabi 您所在的位置:网站首页 ffmpeg media encoder安卓汉化版 编译ffmpeg安卓库(clang篇),含armeabi

编译ffmpeg安卓库(clang篇),含armeabi

2023-08-17 06:05| 来源: 网络整理| 查看: 265

    安卓新的NDK编译工具替换成了clang,所以之前的编译脚本需要做相应调整,本文总结了编译过程中遇到的诸多问题,如果编译过程中遇到问题,或编出的库不符合需求,可参考后面的问题总结,希望能帮到你

环境

    编译环境:win10 + msys2  

    DNK版本:android-ndk-21.2.6472646/ android-ndk-21.0.6113669/android-ndk-r20

   ffmpeg版本: ffmpeg3.3.9/ffmpeg4.3.1

使用本文的编译脚本,测试了linux和window10,android-ndk-21.2.6472646/ android-ndk-21.0.6113669/android-ndk-r20,编译了 ffmpeg3.3.9/ffmpeg4.3.1,都能成功编译

环境搭建

    网上许多安装类unix运行环境都需要翻墙,要么安装速度很慢,本文使用国内源不需要翻墙,如果你安装了其他的类unix运行环境(如cywin, MinGW),理论上应该是可以直接进入后面的编译步骤的,不过我没尝试过

1、msys2安装 

         在清华大学镜像网站下载并安装 msys2 最新版本 ,此外还有中科大,北京理工大学, 上海交大等镜像源,64位系统建议下载x86_64版本,安装一路点击下一步就行

2、msys2配置

        将默认源地址替换为清华大学镜像地址,类似于Ubuntu设置镜像源,这样安装其他工具速度会快很多,配置步骤如下

        见清华大学镜像网站msys2帮助文档,我下载的最新版本默认有许多国内镜像源在配置文件中,其他镜像源的没有试过,建议把国内的源放前面,我的配置顺序如下

#清华大学 Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686/ #中科大 Server = http://mirrors.ustc.edu.cn/msys2/mingw/i686/ #北京理工大学 Server = http://mirror.bit.edu.cn/msys2/mingw/i686/ Server = https://mirror.selfnet.de/msys2/mingw/i686/ #上海交大 Server = https://mirrors.sjtug.sjtu.edu.cn/msys2/mingw/i686/ Server = https://mirror.yandex.ru/mirrors/msys2/mingw/i686/ Server = https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686/ Server = https://www2.futureware.at/~nickoe/msys2-mirror/mingw/i686/

配置完打开安装路径下msys2.exe(或按win键在程序列表中打开),执行 pacman -Sy 刷新软件包数据即可。

       然后执行安装路径下msys2_shell.cmd打开msys终端,执行"pacman -Syuu"命令,中途可能会提示关闭终端,此时关闭msys,重新         打   开,再次执行"pacman -Syuu"命令,更新软件包

    这里顺便附一个pacman包管理工具命令开始编译

3、安装make

    在msys2终端执行pacman -S make,安装make工具

pacman -S make 编译ffmpeg

    msys2安装目录下打开mingw64.exe, 切换到ffmpeg源码路径,windows D:盘被挂载为/d/,以此类推,可用 df -h命令确认,不过盘符占用比较多时相应可能比较慢

    新建一个buid.sh,将以下内容粘贴到文本,根据需求替换前三个变量,如果使用windows文本编辑器,切记保存为unix格式,否则可能会由于结束符不一致问题,报有语法错误,脚本加了一些辅助调试信息,和交互选项,所以比较长,将脚本保存到ffmpeg源码路径下,执行./build 5 ,可编译armeabi-v7a , arm64-v8a, x86, x86_64 所有动态和静态库,如果只编译某个版本的库执行./build可以看到编译选择,选择相应版本编号即可,输出路径下build.log可跟踪编译情况

#!/bin/bash #ffmpeg 版本 FFMPEG_VERSION=4.3.1 #NDK 路径, 根据情况替换 export NDK=/d/Green_Sorft/Android/Sdk/ndk/21.2.6472646 #编译输出路径 根据需求替换替换,默认在脚本上级目录ffmpeg_for_android目录下 OUT_DIR="`dirname $PWD`/ffmpeg_for_android/ffmpeg_${FFMPEG_VERSION}_lib" #编译工具路径,linux版本需根据情况替换 TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/windows-x86_64 export TMPDIR=$OUT_DIR/tmp mkdir -p $TMPDIR #将ndk下yasm所在路径添加到PATH环境变量 PATH=$PATH:$TOOLCHAIN/bin #创建/清空编译日志 > $OUT_DIR/build.log function build_start() { echo "build FFmpeg for $ABI" ./configure \ --prefix=$OUT_DIR/$ABI \ --disable-gpl \ --enable-shared \ --enable-static \ --disable-doc \ --disable-programs \ --disable-avdevice \ --disable-doc \ --disable-symver \ --cross-prefix=$CROSS_PREFIX \ --target-os=android \ --enable-cross-compile \ --arch=$ARCH \ --cpu=$CPU \ --cc=$CC \ --cxx=$CXX \ --sysroot=$TOOLCHAIN/sysroot \ --extra-cflags="-Os -fPIC $OPTIMIZE_CFLAGS" \ configRet=$? echo "* config for $ABI ret:$configRet" >> $OUT_DIR/build.log if [ $configRet -eq 0 ]; then echo "start make $ABI" make clean make -j64 makeRet=$? echo "* make for $ABI return:$makeRet" >> $OUT_DIR/build.log if [ $makeRet -eq 0 ]; then make install mv_libs fi else echo "The config of FFmpeg for $ABI is failded" echo "* config for $ABI failed !!" >> $OUT_DIR/build.log fi echo "The Compilation of FFmpeg for $ABI is completed" echo "*************************" >> $OUT_DIR/build.log } function mv_libs() { mkdir -p $OUT_DIR/shared-libs/$ABI mv $OUT_DIR/$ABI/lib/*.so $OUT_DIR/shared-libs/$ABI mkdir -p $OUT_DIR/static-libs/$ABI mv $OUT_DIR/$ABI/lib/*.a $OUT_DIR/static-libs/$ABI cp -rf $OUT_DIR/$ABI/include $OUT_DIR/ cp -rf $OUT_DIR/$ABI/share/ffmpeg/examples $OUT_DIR/ rm -rf $OUT_DIR/$ABI/ } #armv8-a aarch64 function build_arm64() { API=21 ABI=arm64-v8a ARCH=arm64 CPU=armv8-a CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++ CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android- OPTIMIZE_CFLAGS="-march=$CPU" echo "* buidl for $ABI start !!" >> $OUT_DIR/build.log build_start echo "* buidl for $ABI end !!" >> $OUT_DIR/build.log echo "*************************" >> $OUT_DIR/build.log } #armv7-a function build_arm() { API=16 ABI=armeabi-v7a ARCH=arm CPU=armv7-a CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++ CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi- OPTIMIZE_CFLAGS="-march=$CPU -mfloat-abi=softfp -mfpu=vfp -marm" echo "* buidl for $ABI start !!" >> $OUT_DIR/build.log build_start echo "* buidl for $ABI end !!" >> $OUT_DIR/build.log echo "*************************" >> $OUT_DIR/build.log } #x86 i686 function build_x86() { API=16 ABI=x86 ARCH=x86 CPU=x86 CC=$TOOLCHAIN/bin/i686-linux-android$API-clang CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++ CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android- OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32 -mno-stackrealign" echo "* buidl for $ABI start !!" >> $OUT_DIR/build.log build_start echo "* buidl for $ABI end !!" >> $OUT_DIR/build.log echo "*************************">> $OUT_DIR/build.log echo "">> $OUT_DIR/build.log } #x86_64 function build_x86_64() { API=21 ABI=x86_64 ARCH=x86_64 CPU=x86-64 CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++ CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android- OPTIMIZE_CFLAGS="-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel" echo "* buidl for $ABI start !!" >> $OUT_DIR/build.log build_start echo "* buidl for $ABI end !!" >> $OUT_DIR/build.log echo "*************************">> $OUT_DIR/build.log } function read_opt() { echo "" echo "please select onece" echo " 1、build for ABI=armeabi-v7a CPU=armv7-a" echo " 2、build for ABI=arm64-v8a CPU=armv8-a" echo " 3、build for ABI=x86 CPU=x86" echo " 4、build for ABI=x86_64 CPU=x86_64" echo " 5、build all" echo "" echo "input:" read option } option=$1 if [ "$option" = "" ];then read_opt fi if [ "$option" = "1" ];then echo "start build ABI=arm64-v8a CPU=armv8-a" build_arm64 elif [ "$option" = "2" ];then echo "start build ABI=armeabi-v7a CPU=armv7-a" build_arm elif [ "$option" = "3" ];then echo "start build ABI=x86 CPU=x86" build_x86 elif [ "$option" = "4" ];then echo "start build ABI=x86_64 CPU=x86_64" build_x86_64 elif [ "$option" = "5" ];then echo "start build all" build_arm64 build_arm build_x86 build_x86_64 else echo "invalid input" fi rm -rf $TMPDIR 问题总结 1、编译x86cpu时内联汇编报错

In file included from libswscale/x86/rgb2rgb.c:102: libswscale/x86/rgb2rgb_template.c:1666:13: error: inline assembly requires more registers than available             "mov                        %4, %%"FF_REG_a"\n\t"             ^

提供了一下4个解决方案

1、禁用asm,在ffmpeg configure选项中添加--disable-asm禁用汇编,不过可能会影响运行效率

2、在修改ffmpeg路径下config.h,将HAVE_EBP_AVAILABLE 设置为0 #define HAVE_EBP_AVAILABLE 0

3、这是ndk低版本编译链中才存在的问题,可用24及以上版本编译链,及将脚本中x86_build中的API设置为24及以上(可能会影响兼容性)

4、(推荐)在configure --extra-cflags选项中添加 -mno-stackrealign编译选项

2、使用ffmpeg动态库,编译时提示找不到动态库

在app下build.gradle 文件android内添加如下代码

sourceSets.main{ jniLibs.srcDirs=['libs'] } 3、使用模拟器调试时,提示java.lang.UnsatisfiedLinkError: dlopen failed: "xxx.so" has text relocations(https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-Enforced-for-API-level-23)

模拟器基本都是x86cpu,网上说只有6.0以上才有这个问题,网上的方案都是把aap下build.gradle中的targetSdkVersion设置为23以下,但是我用模拟器调试时似乎不能这么操作,修改后编不出APK,我是搞安卓framework的,应用相关的不是很清楚,所以我直接使用静态库了,或者使用手机

4,提示找不到ysam或版本过低

首先在msys终端输入yasm,看是否有这个命令,如果提示找不到命令,则在脚本中将ndk中android-ndk-r20\toolchains\llvm\prebuilt\windows-x86_64\bin\yasm添加到PATH环境变量中,PATH=$PATH:$TOOLCHAIN/bin ,如果有yasm,则用whereis yasm命令,找到电脑中的yasm,将其重命名(记得改回去)或直接删除,然后将ndk的yasm添加到path环境变量

5、在编译armv7-a时,汇编文件报错

libswscale/arm/rgb2yuv_neon_common.S:251:11: error: unexpected token in argument list CO_BV .dn d2.s16[2]           ^ :4:5: error: invalid instruction     vmul y16x16_l, n16x16_l, CO_RY     ^ 我在编译ffmpeg4.3.1时没有这个问题,但是编译ffmpeg3.3.9时报错,简单粗暴的操作就是在ffmpeg configure选项中添加--disable-asm禁用汇编,但是我们要斯文一点,可以选择只禁用neon,即在armv7-a的ffmpeg configure选项中加入--disable-neon

6、将ffmpeg所有的库编译为一个libffmpeg.so库

目前只编译出静态库,动态库编译编译过程遇到了些问题,后面尝试解决

将多个静态库合并为一个静态库(使用安卓NDK编译链)_mvp_Dawn的博客-CSDN博客_多个静态库打包一个静态库



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有